/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */

/* 
 * File:   KKSIndex.cpp
 * Author: ever
 * 
 * Created on 2018年5月10日, 上午11:12
 */

#include "KKSIndex.h"

/**
 * 文件存储格式 id,kks\n
 * @param index_file
 */
KKSIndex::KKSIndex(const string &index_file) {
    attach(index_file);
}

KKSIndex::~KKSIndex() {
    save();
}

void KKSIndex::attach(const string &index_file) {
    _kks_id.clear();
    _id_kks.clear();
    _save_file = index_file;
    if (!TL_Common::isFileExistEx(index_file)) return;
    std::ifstream file;
    file.open(index_file.c_str(), std::ios_base::in);
    if (!file.is_open()) {
        //throw TL_Exp(std::string("KKSIndex Can't open ") + index_file);
        return;
    }

    int index = 0;
    vector<string> fields;
    string line, kks;
    while (!file.eof()) {
        getline(file, line);
        TL_Common::split(fields, line, ",");
        if (fields.size() < 2) {
            continue;
        }

        index = atoi(fields[0].c_str());
        kks = TL_Common::trim(fields[1]);
        if (kks.empty() || _kks_id.find(kks) != _kks_id.end()) continue;

        auto ret = _kks_id.insert(make_pair(kks, index));
        _id_kks[index] = &(ret.first->first);
    }
    _save_file = index_file;
}

u32_t KKSIndex::getKKSId(const string &kks) {
    if (empty()) {
        return atoll(kks.c_str());
    }
    auto it = _kks_id.find(kks);
    if (it == _kks_id.end()) {
        return 0;
    }
    return it->second;
}

u32_t KKSIndex::addKKS(const string &kks) {
    auto it = _kks_id.find(kks);
    if (it != _kks_id.end()) {
        return it->second;
    }
    u32_t index = _kks_id.size() + 1;
    auto ret = _kks_id.insert(make_pair(kks, index));
    _id_kks[index] = &(ret.first->first);
    _need_save = true;
    return index;
}

const string &KKSIndex::getKKS(u32_t id) {
    auto it = _id_kks.find(id);
    if (it != _id_kks.end()) {
        return *it->second;
    } else {
        static string empty;
        return empty;
    }
}

void KKSIndex::save() {
    if (!_need_save) return;
    string tmp;
    tmp.reserve(4096);

    enum {
        buffsize = 1024
    };
    char c[buffsize];
    int len;
    auto it = _id_kks.begin();
    while (it != _id_kks.end()) {
        len = snprintf(c, buffsize, "%u,%s\n", it->first, it->second->c_str());
        tmp.append(c, len);
        ++it;
    }
    std::ofstream file;
    file.open((_save_file + ".save").c_str(), std::ios_base::out | std::ios_base::trunc);
    file.write(tmp.c_str(), tmp.size());
    file.close();
    try {
        TL_Common::unlink(_save_file);
    } catch (const TL_Exp &e) {
        cerr << e.what() << endl;
    }
    TL_Common::rename((_save_file + ".save"), _save_file);
    _need_save = false;
}
